<template>
  <div :class="[{ 'app-container': !this.$route.query.appName }]">
    <div class="filter-container">
      <el-input
        v-model="listQuery.appName"
        placeholder="服务名称"
        style="width: 400px"
        class="filter-item"
        size="small"
        :disabled="mode === 'single'"
        @keyup.enter.native="handleFilter"
      />
      <el-select
        v-model="listQuery.type"
        placeholder="规则类型"
        clearable
        style="width: 120px;"
        class="filter-item"
        size="small"
      >
        <el-option v-for="item in typeOptions" :key="item.key" :label="item.value" :value="item.key" />
      </el-select>

      <el-button class="filter-item" type="primary" icon="el-icon-search" size="small" @click="handleFilter">
        查询
      </el-button>
      <el-button class="filter-item" type="primary" size="small" icon="el-icon-edit" @click="handleCreate">
        新建
      </el-button>
    </div>

    <el-table
      v-loading="listLoading"
      :data="list"
      element-loading-text="Loading"
      border
      fit
      highlight-current-row
      style="width: 100%"
    >
      <el-table-column v-if="!this.$route.query.appName" label="服务名称" min-width="300">
        <template slot-scope="scope">
          {{ scope.row.app }}
        </template>
      </el-table-column>
      <el-table-column label="规则类型" width="120">
        <template slot-scope="scope">
          {{ typeMap[scope.row.type] }}
        </template>
      </el-table-column>
      <el-table-column label="状态" width="70">
        <template slot-scope="scope">
          <el-tag :type="enabledStatusFilter(scope.row.enabled)">
            {{ scope.row.enabled ? "启用" : "禁用" }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="请求方法">
        <template slot-scope="scope">
          {{ scope.row.method }}
        </template>
      </el-table-column>
      <el-table-column label="API" width="220">
        <template slot-scope="scope">
          {{ scope.row.api }}
        </template>
      </el-table-column>
      <el-table-column label="生效服务" width="250">
        <template slot-scope="scope">
          {{ scope.row.limitedServiceList.join(",") }}
        </template>
      </el-table-column>
      <el-table-column label="外部调用">
        <template slot-scope="scope">
          <el-tag :type="enabledStatusFilter(scope.row.includeNonEureka)">
            {{ scope.row.includeNonEureka ? "生效" : "不生效" }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="授权策略">
        <template slot-scope="scope">
          {{ strategyMap[scope.row.strategy] }}
        </template>
      </el-table-column>
      <el-table-column label="限流策略">
        <template slot-scope="scope">
          {{ gradeMap[scope.row.grade] }}
        </template>
      </el-table-column>
      <el-table-column label="限流阈值" width="80">
        <template slot-scope="scope">
          {{ scope.row.count }}
        </template>
      </el-table-column>
      <el-table-column label="更新时间" width="160">
        <template slot-scope="scope">
          {{ scope.row.updatedTime }}
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" width="120" fixed="right" class-name="small-padding fixed-width">
        <template slot-scope="{ row }">
          <el-button type="text" size="mini" @click="handleUpdate(row)">
            编辑
          </el-button>
          <el-button type="text" size="mini" class="btn-cancel" @click="handleDelete(row)">
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="listQuery.pageNo"
      :limit.sync="listQuery.pageSize"
      @pagination="fetchData"
    />

    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
      <el-form
        ref="dataForm"
        :rules="rules"
        :model="temp"
        label-position="left"
        label-width="80px"
        size="small"
        style="width: 500px; margin-left: 50px"
      >
        <el-form-item label="服务" prop="app">
          <el-select
            v-model="temp.app"
            :disabled="dialogStatus !== 'create' || this.$route.query.appName"
            clearable
            filterable
            class="filter-item"
            style="width: 430px"
          >
            <el-option v-for="item in appOptions" :key="item" :label="item" :value="item" />
          </el-select>
        </el-form-item>
        <el-form-item label="规则类型" prop="type">
          <el-select
            v-model="temp.type"
            :disabled="dialogStatus !== 'create'"
            placeholder="规则类型"
            clearable
            class="filter-item"
            style="width: 430px"
            @change="onRuleTypeChange"
          >
            <el-option v-for="item in typeOptions" :key="item.key" :label="item.value" :value="item.key" />
          </el-select>
        </el-form-item>
        <el-form-item label="API" prop="method">
          <el-tooltip effect="dark" content="'ALL' 表示所有 API" placement="top-end">
            <el-input v-model="temp.api" style="width: 430px">
              <el-select
                slot="prepend"
                v-model="temp.method"
                placeholder="请求方法"
                class="filter-item"
                style="width: 120px"
              >
                <el-option v-for="item in methodOptions" :key="item.key" :label="item.value" :value="item.key" />
              </el-select>
            </el-input>
          </el-tooltip>
        </el-form-item>
        <el-form-item label="生效服务" prop="limitedServiceList">
          <el-select
            v-model="temp.limitedServiceList"
            multiple
            clearable
            filterable
            class="filter-item"
            style="width: 430px"
          >
            <el-option v-for="item in enabledAppOptions" :key="item" :label="item" :value="item" />
          </el-select>
        </el-form-item>
        <el-form-item label="外部调用" prop="enabled">
          <el-switch v-model="temp.includeNonEureka" active-color="#13ce66" inactive-color="#ff4949" />
        </el-form-item>
        <el-form-item v-show="temp.type == 1" label="授权策略" prop="strategy">
          <el-select v-model="temp.strategy" placeholder="授权策略" class="filter-item" style="width: 430px">
            <el-option v-for="item in strategyOptions" :key="item.key" :label="item.value" :value="item.key" />
          </el-select>
        </el-form-item>
        <el-form-item v-show="temp.type == 2" label="限流策略" prop="grade">
          <el-select v-model="temp.grade" placeholder="限流策略" class="filter-item" style="width: 430px">
            <el-option v-for="item in gradeOptions" :key="item.key" :label="item.value" :value="item.key" />
          </el-select>
        </el-form-item>
        <el-form-item v-show="temp.type == 2" label="限流阈值" prop="count">
          <el-input v-model="temp.count" style="width: 430px" oninput="value=value.replace(/[^0-9.]/g,'')" />
        </el-form-item>
        <el-form-item label="是否启用" prop="enabled">
          <el-switch v-model="temp.enabled" active-color="#13ce66" inactive-color="#ff4949" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" @click="dialogFormVisible = false"> 取消 </el-button>
        <el-button type="primary" size="small" @click="dialogStatus === 'create' ? createData() : updateData()">
          确认
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getList, saveRule, deleteRule } from '@/api/rule'
import { listAppNames } from '@/api/app'
import Pagination from '@/components/Pagination'
import waves from '@/directive/waves'
import { Message } from 'element-ui'

export default {
  // name: '服务列表',
  components: { Pagination },
  directives: { waves },
  filters: {
    statusFilter(status) {
      const statusMap = {
        published: 'success',
        draft: 'gray',
        deleted: 'danger'
      }
      return statusMap[status]
    }
  },
  props: {
    mode: {
      type: String,
      default: 'all'
    }
  },
  data() {
    return {
      list: null,
      total: 0,
      listLoading: true,
      listQuery: {
        pageNo: 1,
        pageSize: 10,
        appName: this.$route.query.appName,
        type: this.$route.query.ruleType
      },
      textMap: {
        update: '编辑规则',
        create: '新建规则'
      },
      appOptions: [],
      enabledAppOptions: [],
      typeOptions: [
        {
          key: 1,
          value: '授权规则'
        },
        {
          key: 2,
          value: '限流规则'
        }
      ],
      typeMap: {
        1: '授权',
        2: '限流'
      },
      methodOptions: [
        {
          key: 'ALL',
          value: 'ALL'
        },
        {
          key: 'GET',
          value: 'GET'
        },
        {
          key: 'POST',
          value: 'POST'
        },
        {
          key: 'PUT',
          value: 'PUT'
        },
        {
          key: 'DELETE',
          value: 'DELETE'
        },
        {
          key: 'PATCH',
          value: 'PATCH'
        },
        {
          key: 'HEAD',
          value: 'HEAD'
        },
        {
          key: 'OPTIONS',
          value: 'OPTIONS'
        },
        {
          key: 'CONNECT',
          value: 'CONNECT'
        },
        {
          key: 'TRACE',
          value: 'TRACE'
        }
      ],
      strategyOptions: [
        {
          key: 1,
          value: '黑名单'
        },
        {
          key: 0,
          value: '白名单'
        }
      ],
      strategyMap: {
        1: '黑名单',
        0: '白名单'
      },
      gradeOptions: [
        {
          key: 1,
          value: 'QPS'
        },
        {
          key: 0,
          value: '并发数'
        }
      ],
      gradeMap: {
        1: 'QPS',
        0: '并发数'
      },
      temp: {
        id: undefined,
        app: this.$route.query.appName,
        method: 'ALL',
        api: 'ALL',
        limitedServiceList: [],
        strategy: null,
        grade: null,
        count: null,
        enabled: true,
        includeNonEureka: true
      },
      dialogFormVisible: false,
      dialogStatus: '',
      deleteReq: {
        ruleId: undefined
      },
      rules: {
        app: [{ required: true, message: '请选择服务', trigger: 'change' }],
        type: [{ required: true, message: '请选择规则类型', trigger: 'change' }]
      }
    }
  },
  created() {
    this.fetchData()
    this.fetchApps()
  },
  methods: {
    fetchData() {
      this.listLoading = true
      getList(this.listQuery).then((response) => {
        this.total = response.data.total
        this.list = response.data.items
        this.listLoading = false
      }).catch(() => {
        this.listLoading = false
      })
    },
    fetchApps() {
      listAppNames().then((response) => {
        this.appOptions = response.data
        this.enabledAppOptions = Object.assign(this.enabledAppOptions, this.appOptions) // copy obj
        this.enabledAppOptions.unshift('ALL')
      })
    },
    handleFilter() {
      this.listQuery.pageNo = 1
      this.fetchData()
    },
    resetTemp() {
      this.temp = {
        id: undefined,
        app: this.$route.query.appName,
        method: 'ALL',
        api: 'ALL',
        limitedServiceList: [],
        strategy: null,
        grade: null,
        count: null,
        enabled: true,
        includeNonEureka: true
      }
    },
    handleCreate() {
      this.resetTemp()
      this.dialogStatus = 'create'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    handleUpdate(row) {
      this.temp = Object.assign({}, row) // copy obj
      this.dialogStatus = 'update'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    handleDelete(row) {
      this.$confirm('是否确认删除此规则?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.doDelete(row)
      })
    },
    doDelete(row) {
      deleteRule({ ruleId: row.id }).then(() => {
        // const index = this.list.findIndex(v => v.id === this.temp.id)
        // this.list.splice(index, 1, this.temp)
        this.fetchData()
        this.$notify({
          title: '成功',
          message: '删除成功',
          type: 'success',
          duration: 2000
        })
      })
    },
    updateData() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          const tempData = Object.assign({}, this.temp)
          const msg = this.validRule(tempData)
          if (msg) {
            Message({
              message: msg,
              type: 'warning',
              duration: 2 * 1000
            })
          } else {
            saveRule(tempData).then(() => {
              const index = this.list.findIndex((v) => v.id === this.temp.id)
              this.list.splice(index, 1, this.temp)
              this.dialogFormVisible = false
              this.$notify({
                title: '成功',
                message: '更新成功',
                type: 'success',
                duration: 2000
              })
            })
          }
        }
      })
    },
    createData() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          const tempData = Object.assign({}, this.temp)
          saveRule(tempData).then(() => {
            this.dialogFormVisible = false
            this.$notify({
              title: '成功',
              message: '创建成功',
              type: 'success',
              duration: 2000
            })
            this.fetchData()
          })
        }
      })
    },
    enabledStatusFilter(status) {
      const statusMap = {
        true: 'success',
        false: 'danger'
      }
      return statusMap[status]
    },
    onRuleTypeChange(val) {
      if (val === 1 && this.temp.strategy == null) {
        this.temp.strategy = 1
        this.temp.grade = null
        this.temp.count = null
      } else if (val === 2 && this.temp.grade == null) {
        this.temp.strategy = null
        this.temp.grade = 1
      }
    },
    validRule(rule) {
      if (rule.type === 1) {
        if (rule.strategy == null) {
          return '请选择授权策略'
        }
      } else if (rule.type === 2) {
        if (rule.count == null || rule.count <= 0) {
          return '请输入正确的限流阈值'
        }
      }
      return null
    }
  }
}
</script>
